/*
 * 文件名：PushServiceImpl.java
 * 版权：
 * 描述：TODO
 * 修改人：zuo liubo
 * 修改时间：2013-3-26 下午2:40:33
 */
package com.scpii.api.service.push.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.scpii.api.common.Constants;
import com.scpii.api.domain.auth.Devices;
import com.scpii.api.domain.auth.UsersInfoDetails;
import com.scpii.api.domain.push.Message;
import com.scpii.api.domain.push.UserMessageDevices;
import com.scpii.api.domain.push.UserMessages;
import com.scpii.api.persistence.auth.UserDevicesMapper;
import com.scpii.api.persistence.push.MessageMapper;
import com.scpii.api.persistence.push.UserMessageDevicesMapper;
import com.scpii.api.persistence.push.UserMessagesMapper;
import com.scpii.api.persistence.user.UsersMapper;
import com.scpii.api.service.push.PushService;
import com.scpii.api.service.push.apns.ApnsUtil;
import com.scpii.api.util.PrincipalUtil;

/**
 * @description 推送相关service服务
 * @author zuo liubo
 * @date 2013-3-26
 */
@Service("pushService")
public class PushServiceImpl implements PushService {

	@Resource
	private UserMessageDevicesMapper userMessageDevicesMapper;
	@Resource
	private UserMessagesMapper userMessagesMapper;
	@Resource
	private MessageMapper messageMapper;
	@Resource
	private UsersMapper usersMapper;
	@Resource
	private UserDevicesMapper userDevicesMapper;

	private List<UserMessageDevices> list = new ArrayList<UserMessageDevices>();

	@Override
	public List<UserMessageDevices> getMessageByUser(Long userId, long deviceId, Long appId) {
		UserMessageDevices userMessageDevices = new UserMessageDevices();
		userMessageDevices.setUserId(userId);
		userMessageDevices.setDeviceId(deviceId);
		userMessageDevices.setAppId(appId);
		userMessageDevices.setMessageStatus(Message.status.OK_SEND);
		list = userMessageDevicesMapper.androidPullMessage(userMessageDevices);

		updateMessageStatus(list);
		return list;
	}

	@Override
	public boolean deleteUserMessageByObject(UserMessages userMessages) {
		int affectRow = userMessagesMapper.deleteByObject(userMessages);
		return affectRow > 0;
	}

	@Override
	public List<UserMessages> getUserMessageByUserId(Long userId) {
		UserMessages userMessages = new UserMessages();
		userMessages.setUserId(userId);
		return userMessagesMapper.selectUserMessageByUserId(userMessages);
	}

	@Override
	public List<UserMessageDevices> selectUserMessageDevicesById(Long messageId, int type) {
		UsersInfoDetails u = PrincipalUtil.getPrincipal();
		Long userId = u.getId();
		Long appId = u.getAppId();
		Long deviceId = u.getDeviceId();

		UserMessageDevices userMessageDevices = new UserMessageDevices();
		userMessageDevices.setUserId(userId);
		userMessageDevices.setAppId(appId);
		userMessageDevices.setDeviceId(deviceId);
		userMessageDevices.setMessageStatus(Message.status.HAS_PUSH);
		if (type == 0) {
			userMessageDevices.setMessageId(messageId);
		}
		list = userMessageDevicesMapper.selectByObject(userMessageDevices);
		updateMessageStatus(list);
		return list;
	}

	@Override
	public void updateMessageStatus(Object... objects) {
		@SuppressWarnings("unchecked")
		List<UserMessageDevices> list = (List<UserMessageDevices>) objects[0];
		if (list.size() == 0)
			return;
		List<Long> idList = new ArrayList<Long>();
		List<Long> userMessageIdList = new ArrayList<Long>();
		for (UserMessageDevices umd : list) {
			idList.add(umd.getUserMessageDevicesId());
			userMessageIdList.add(umd.getUserMessageId());
		}
		// 更新PNS_USER_MESSAGE_DEVICE表
		userMessageDevicesMapper.updateMessageStatusToHAS_PULL(idList);
		// 更新PNS_USER_MESSAGE表
		userMessagesMapper.updateMessageStatusToHAS_PULL(userMessageIdList);
	}

	@Override
	public boolean insertMessage(Message message, String userId, String userName) {
		UsersInfoDetails u = PrincipalUtil.getPrincipal();
		List<Long> userIdList = new ArrayList<Long>();
		Long appId = u.getAppId();
		message.setAppId(appId);
		userIdList = getUserIdList(userId, userName, appId);
		// 用户没有传递该值，则使用默认值
		if (message.getStartTime() == null)
			message.setStartTime(new Date());
		if (message.getExpireTime() == null) {
			Calendar c = Calendar.getInstance();
			c.set(Calendar.DATE, c.get(Calendar.DATE) + 1);
			message.setExpireTime(c.getTime());
		}
		message = insertMessage(message);
		// TODO 需要进行优化 优化为批量插入数据
		for (Long _userId : userIdList) {
			UserMessages userMessages = insertUserMessages(_userId, message);
			insertUserMessageDevices(message, userMessages);
		}
		return true;
	}

	/**
	 * 根据传递的参数返回用户ID，如果指定了userId就直接返回；指定了userName，则将userName转换为userId； 如果userId
	 * 和 userName都没有指定就返回该应用的所有用户id
	 * 
	 * @p1aram userId
	 * @param userName
	 * @param appId
	 * @return
	 */
	private List<Long> getUserIdList(String userId, String userName, Long appId) {
		List<Long> userIdList = new ArrayList<Long>();
		if (userId != null) { // 使用用户ID进行选择发送对象
			String[] userIdArray = userId.split(Constants.ID_SEPARATOR);
			for (String _userId : userIdArray) {
				userIdList.add(Long.parseLong(_userId));
			}
		} else if (userName != null) { // 使用用户名进行选择发送对象
			List<String> userNameList = new ArrayList<String>();
			String[] userNameArray = userName.split(Constants.ID_SEPARATOR);
			for (String _userName : userNameArray) {
				userNameList.add(_userName);
			}
			userIdList = usersMapper.selectUserIdByUserName(userNameList, appId);
		} else { // 用户名和用户ID均为空的情况下表示向该应用的所有用户都发送信息
			userIdList = getUserIds(appId);
		}
		return userIdList;
	}

	/**
	 * 根据应用ID来获取该用户的所有用户ID
	 * 
	 * @param appId
	 *            应用ID
	 * @return
	 */
	private List<Long> getUserIds(Long appId) {
		return usersMapper.selectUserIdByAppId(appId);
	}

	/**
	 * 插入 用户消息设备表
	 * 
	 * @param message
	 *            消息体
	 * @param userMessages
	 *            用户消息
	 */
	private void insertUserMessageDevices(Message message, UserMessages userMessages) {
		UserMessageDevices umd = new UserMessageDevices();
		umd.setUserMessageId(userMessages.getUserMessageId());
		umd.setMessageId(message.getMessageId());
		umd.setAppId(message.getAppId());
		umd.setTitle(message.getTitle());
		umd.setIcon(message.getIcon());
		umd.setSummary(message.getSummary());
		umd.setBody(message.getBody());
		umd.setStartTime(message.getStartTime());
		umd.setExpireTime(message.getExpireTime());
		umd.setCreateTime(new Date());
		umd.setMessageStatus(Message.status.OK_SEND);
		umd.setUserId(userMessages.getUserId());

		List<UserMessageDevices> list = getUserMessageDevices(umd);
		// TODO 可以进行优化为 【批量插入】
		for (UserMessageDevices userMessageDevices : list) {
			userMessageDevicesMapper.insert(userMessageDevices);
		}
	}

	/**
	 * 根据userId 和 appId 查找该用户目前在那些设备上登陆
	 * 
	 * @param umd
	 * @return
	 */
	private List<UserMessageDevices> getUserMessageDevices(UserMessageDevices umd) {
		List<UserMessageDevices> list = new ArrayList<UserMessageDevices>();
		List<Devices> loginOnlist = userDevicesMapper.selectLoginOnDevicesByUserId(umd.getUserId());
		for (Devices d : loginOnlist) {
			if (d.getIosToken() != null)
				ApnsUtil.validateIOSToken(d.getIosToken());
			UserMessageDevices _umd = (UserMessageDevices) umd.clone();
			_umd.setDeviceId(d.getId());
			_umd.setIosToken(d.getIosToken());
			list.add(_umd);
		}
		return list;
	}

	/**
	 * 向USER_MESSAGE表插入记录
	 * 
	 * @param userId
	 *            用户ID
	 * @param messageId
	 *            消息ID
	 */
	private UserMessages insertUserMessages(Long userId, Message message) {
		UserMessages userMessages = new UserMessages();
		Long id = userMessagesMapper.generateId();
		userMessages.setUserMessageId(id);
		userMessages.setUserId(userId);
		userMessages.setMessage(message);
		userMessages.setMessageStatus(Message.status.NONE_SEND);
		userMessagesMapper.insert(userMessages);
		return userMessages;
	}

	/**
	 * 向PNS_MESSAGES表插入记录
	 * 
	 * @param message
	 */
	private Message insertMessage(Message message) {
		Long messageId = messageMapper.generateId();
		message.setMessageId(messageId);
		message.setCreateTime(new Date());
		message.setMessageStatus(Message.status.OK_SEND);
		messageMapper.insert(message);
		return message;
	}

	@Override
	public void messageStatusToHasPush(UserMessageDevices umd, List<String> iosTokens) {
		umd.setMessageStatus(Message.status.HAS_PUSH);
		userMessageDevicesMapper.updateMessageStatusToHAS_PUSH(umd, iosTokens);
	}

	@Override
	public int updateMessageToRead(Long userMessageId, Long userId) {
		return userMessagesMapper.updateUserMessageStatus(userMessageId, Message.status.HAS_READ);
	}

	@Override
	public int updateMessageStatusByIosToken(UserMessageDevices umd, List<String> iosTokens) {
		Long appId = umd.getAppId();
		Long messageId = umd.getMessageId();
		return userMessagesMapper.updateUserMessageStatusByIosToken(appId, iosTokens, messageId);
	}

	@Override
	public int selectNotReadCountByUserId(Long userId) {
		// TODO Auto-generated method stub
		return userMessagesMapper.selectNotReadCountByUserId(userId);
	}

	@Override
	public int updateStatus4Test(Long userMessageDeviceId, Integer messageStatus) {
		// TODO Auto-generated method stub
		return userMessageDevicesMapper.updateStatus4Test(userMessageDeviceId, messageStatus);
	}

}
